﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Timers;
using System.Windows.Forms;

namespace ParticleEditor
{
    class ParticleEmitter
    {
        private List<Particle> live_particles = new List<Particle>();
        private Queue<Particle> dead_particles = new Queue<Particle>();

        public Color Start, Finish;
        public int Alpha_s, Alpha_f;

        public bool vTimeBase, vPointBase, vCircleBased;

        public bool VCircleBased
        {
            get { return vCircleBased; }
            set { vCircleBased = value; }
        }

        public bool VPointBase
        {
            get { return vPointBase; }
            set { vPointBase = value; }
        }

        public bool VTimeBase
        {
            get { return vTimeBase; }
            set { vTimeBase = value; }
        }

        public int Alpha_s1
        {
            get { return Alpha_s; }
            set { Alpha_s = value; }
        }

        public int Alpha_f1
        {
            get { return Alpha_f; }
            set { Alpha_f = value; }
        }

        public Color Start1
        {
            get { return Start; }
            set { Start = value; }
        }

        public Color Finish1
        {
            get { return Finish; }
            set { Finish = value; }
        }

        private float y;
        public float Y
        {
            get { return y; }
            set { y = value; }
        }

        private float x;
        public float X
        {
            get { return x; }
            set { x = value; }
        }

        public float scale_s, scale_f;

        public float Scale_s
        {
            get { return scale_s; }
            set { scale_s = value; }
        }

        public float Scale_f
        {
            get { return scale_f; }
            set { scale_f = value; }
        }

        float posX_s, posX_f, posY_s, posY_f;
        public float velX_s, velX_f, velY_s, velY_f;

        public float VelX_s
        {
            get { return velX_s; }
            set { velX_s = value; }
        }
        public float VelX_f
        {
            get { return velX_f; }
            set { velX_f = value; }
        }

        public float VelY_s
        {
            get { return velY_s; }
            set { velY_f = value; }
        }

        public float VelY_f
        {
            get { return velY_f; }
            set { velY_f = value; }
        }

        public float PosX_s
        {
            get { return posX_s; }
            set { posX_s = value; }
        }

        public float PosX_f
        {
            get { return posX_f; }
            set { posX_f = value; }
        }

        public float PosY_s
        {
            get { return posY_s; }
            set { posY_s = value; }
        }

        public float PosY_f
        {
            get { return posY_f; }
            set { posY_f = value; }
        }

        private float offX, offY;

        private int numParticles;
        public int NumParticles
        {
            get { return numParticles; }
            set { numParticles = value; }
        }

        private float startTime;
        public float StartTime
        {
            get { return startTime; }
            set { startTime = value; }
        }

        private bool isLooping;
        public bool IsLooping
        {
            get { return isLooping; }
            set { isLooping = value; }
        }

        private float DelayTimer;
        public float delayTimer
        {
            get { return DelayTimer; }
            set { DelayTimer = value; }
        }

        private int particleID;
        public int ParticleID
        {
            get { return particleID; }
            set { particleID = value; }
        }

        private int sourceBlend;
        public int SourceBlend
        {
            get { return sourceBlend; }
            set { sourceBlend = value; }
        }

        private int destinationBlend;
        public int DestinationBlend
        {
            get { return destinationBlend; }
            set { destinationBlend = value; }
        }

        private bool isPlaying;
        public bool IsPlaying
        {
            get { return isPlaying; }
            set { isPlaying = value; }
        }

        private float particleLife;
        public float ParticleLifetime
        {
            get { return particleLife; }
            set { particleLife = value; }
        }
        private float particledelay;
        public float ParticleDelay
        {
            get { return particledelay; }
            set { particledelay = value; }
        }


        private Random randVelocity = new Random();

        public void CreateParticleEmitter()
        {
            velX_s = 0;
            velY_s = 0;

            scale_s = 1;
            scale_f = 1;

            Alpha_f = 255;
            Alpha_s = 255;

            Start1 = Color.White;
            Finish1 = Color.White;

            vPointBase = true;
            vTimeBase = false;
            vCircleBased = false;

            particleLife = 5;

            delayTimer = 0;
            
        }

        public void Reset(Particle particle)
        {
            particle._StartTime = startTime;
            particle._LifeTime = particleLife;
            particle._scale = scale_s;
            particle._velX = velX_f;
            particle._velY = velY_f;
            particle._X = x;
            particle._Y = y;
            particle.A1 = Alpha_s;
            particle.R1 = Start.R;
            particle.G1 = Start.G;
            particle.B1 = Start.B;

        }

        public void StartEmitter()
        {
            for (int i = 0; i != numParticles; i++)
            {
                Particle temp = new Particle(x, y, posX_s, posY_s, scale_f, particleLife, 0);
                //Set emitter
                Reset(temp);
                temp.SetEmitter(this);
                dead_particles.Enqueue(temp);
            }
        }


        public void Render(int ImageID, Point Center)
        {
            if (ImageID < 0)
                return;

            for (int i = 0; i < live_particles.Count; ++i)
            {
                // Render here
                live_particles[i].Render(particleID, Center);
            }
        }

        public void Update(float elapsedTime)
        {

            if (dead_particles.Count > 0 && live_particles.Count < numParticles)
            {
                while (live_particles.Count != numParticles && DelayTimer <= 0)
                {
                    if (posY_s > posY_f)
                    {
                        offY = randVelocity.Next((int)posY_f, (int)posY_s);
                    }
                    else
                    {
                        offY = randVelocity.Next((int)posY_s, (int)posY_f);
                    }

                    if (posX_s > posX_f)
                    {
                        offX = randVelocity.Next((int)posX_f, (int)posX_s);
                    }
                    else
                    {
                        offX = randVelocity.Next((int)posX_s, (int)posX_f);
                    }

                    Particle temp = dead_particles.Dequeue();
                    temp.SetEmitter(this);
                    Reset(temp);
                    if (vTimeBase)
                    {
                        temp._X = offX;
                        temp._Y = offY;
                    }
                    else
                    {
                        temp._velX = offX;
                        temp._velY = offY;
                    }

                    live_particles.Add(temp);

                }

                DelayTimer -= elapsedTime;

                if (DelayTimer < 0)
                    DelayTimer = particledelay;
            }
           

            for (int i = 0; i < live_particles.Count; ++i)
            {
                live_particles[i].Update(elapsedTime,vTimeBase,vCircleBased);

                if (live_particles[i]._LifeTime <= 0)
                {
                    Particle temp = live_particles[i];
                    dead_particles.Enqueue(temp); 
                    live_particles.Remove(temp);
                }
            }



        }

        public void Resize(int size)
        {
            if (size >= numParticles)
            {
                for (int i = 0; i != (size - numParticles); ++i)
                {
                    // needs start values
                    Particle temp = new Particle(x, y, posX_s, posY_s, scale_s, 1);
                    //Set emitter
                    temp.SetEmitter(this);
                    dead_particles.Enqueue(temp);
                }
            }
            else
            {
                dead_particles.Clear();
                for (int i = 0; i != size; i++)
                {
                    Particle temp = new Particle(x, y, posX_s, posY_s, scale_s, 1);
                    //Set emitter
                    temp.SetEmitter(this);
                    dead_particles.Enqueue(temp);
                }
            }
            numParticles = size;
        }


    }
}
